using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows.Forms;

using VSTrid = Microsoft.VisualStudio.VirtualTreeGrid;

using DslEditorPowerToy.Controls.VirtualTreeGrid;
using DslEditorPowerToy.Controls.VirtualTreeGrid.Branches;

using DslEditorPowerToy.Controls.Editors.Special.DomainModelTreeGrid.Data;

namespace DslEditorPowerToy.Controls.Editors.Special.DomainModelTreeGrid.Branches
{
    internal abstract class DomainElementContainerBranch : DomainElementBranch
    {
        #region Constructors
        protected DomainElementContainerBranch(VirtualTreeGridControl treeControl,
            IDomainElementContainer branchData, Type branchDataItemType)
            : base(treeControl, branchData, branchDataItemType)
        {
            SubscribeToEvents();
        }
        #endregion

        #region Protected Properties
        protected new IDomainElementContainer BranchData
        {
            get
            {
                return base.BranchData as IDomainElementContainer;
            }
        }
        #endregion

        #region BranchData Handlers
        private void _branchData_ChildElementAdded(object sender, ChildElementAddedEventArgs e)
        {
            if (this.BranchData is IDomainElementContainer)
            {
                //Find newly added element in children
                int index = GetElementRowIndex(e.AddedElement);
                if (-1 != index)
                {
                    //this.OnBranchDataItemAdded(index);
                    this.OnBranchModified(VSTrid.BranchModificationEventArgs.Realign(this));
                }
            }
        }
        private void _branchData_ChildElementMoved(object sender, ChildElementMovedEventArgs e)
        {
            if (this.BranchData is IDomainElementContainer)
            {
                //Not likely we will be able to find out the source and target rows
                //Can only refresh branch
                this.OnBranchModified(VSTrid.BranchModificationEventArgs.Realign(this));
            }
        }
        private void _branchData_ChildElementRemoved(object sender, ChildElementRemovedEventArgs e)
        {
            if (this.BranchData is IDomainElementContainer)
            {
                //Not likely we will find this in branch data anymore
                //Can only refresh branch
                this.OnBranchModified(VSTrid.BranchModificationEventArgs.Realign(this));
            }
        }
        private void _branchData_PropertiesUpdated(object sender, PropertiesUpdatedEventArgs e)
        {
            //Check special case when branch manages own display
            if (true == e.UpdatedElement.Equals(this.BranchData))
            {
                if (this.BranchData is IDomainPropertyOwner)
                {
                    this.OnBranchDataItemChanged(VSTrid.VirtualTreeDisplayDataChanges.VisibleElements);
                    return;
                }
            }

            //Find element in children
            if (this.BranchData is IDomainElementContainer)
            {
                int index = GetElementRowIndex(e.UpdatedElement);
                if (-1 != index)
                    this.OnBranchDataItemChanged(index);
            }
        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Subscribes to branch item events
        /// </summary>
        private void SubscribeToEvents()
        {
            if (null == this.BranchData)
                return;

            //Subscribe to events of this branch parent element
            if (this.BranchData is IDomainElementContainer)
            {
                this.BranchData.ChildElementAdded += new ChildElementAddedEventHandler(this._branchData_ChildElementAdded);
                this.BranchData.ChildElementRemoved += new ChildElementRemovedEventHandler(this._branchData_ChildElementRemoved);
                this.BranchData.ChildElementMoved += new ChildElementMovedEventHandler(this._branchData_ChildElementMoved);

                DomainElementCollection<IDomainElement> dataItems = this.GetElementRows();
                if (null != dataItems)
                {
                    //Subscribe to child element property update events
                    foreach (IDomainElement dataItem in dataItems)
                    {
                        if (dataItem is IDomainPropertyOwner)
                            dataItem.PropertiesUpdated += new PropertiesUpdatedEventHandler(this._branchData_PropertiesUpdated);
                    }
                }
            }

            //Special case for branches that display themselves
            if (this.BranchData is IDomainPropertyOwner)
                this.BranchData.PropertiesUpdated += new PropertiesUpdatedEventHandler(this._branchData_PropertiesUpdated);
        }
        /// <summary>
        /// Returns the index of the specified element
        /// </summary>
        /// <returns></returns>
        private int GetElementRowIndex(IDomainElement element)
        {
            DomainElementCollection<IDomainElement> childElements = this.GetElementRows();
            if (null != childElements)
            {
                for (int index = 0; index < childElements.Count; index++)
                {
                    IDomainElement childElement = childElements[index];
                    if (true == element.Equals(childElement))
                        return index;
                }
            }

            return -1;
        }
        #endregion
    }
}
